import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:get/get_utils/src/extensions/num_extensions.dart';

/// https://github.com/qq326646683/tech-article/blob/master/flutter/Flutter%E4%B8%8A%E7%BA%BF%E9%A1%B9%E7%9B%AE%E5%AE%9E%E6%88%98%E2%80%94%E2%80%94%E9%98%9F%E5%88%97%E4%BB%BB%E5%8A%A1.md

class QueueUtil<T> {
  QueueUtil._() {
    /// 初始化代码
  }

  /// 用map key存储多个QueueUtil单例,目的是隔离多个类型队列任务互不干扰
  /// Use map key to store multiple QueueUtil singletons, the purpose is to isolate multiple types of queue tasks without interfering with each other
  static final Map<String, QueueUtil<dynamic>> _instance = <String, QueueUtil<dynamic>>{};

  static QueueUtil<T> get<T>(String key) {
    if (_instance[key] == null || _instance[key] is! QueueUtil<T>) {
      _instance[key] = QueueUtil<T>._();
    }
    return _instance[key]! as QueueUtil<T>;
  }

  static QueueUtil<String?> defaultQueue() {
    return get<String?>('default');
  }

  List<TaskInfo<T>> _taskList = [];
  bool _isTaskRunning = false;
  int _mId = 0;
  bool _isCancelQueue = false;

  bool get hasTaskRunning => _isTaskRunning && _taskList.isNotEmpty;

  Function? cancelListener;

  Future<TaskInfo<T>> addTask(
    Future<T> Function() doSomething, {
    String? taskId,
  }) {
    _isCancelQueue = false;
    _mId++;
    final TaskInfo<T> taskInfo = TaskInfo<T>(_mId, taskId, doSomething);

    /// 创建future
    final Completer<TaskInfo<T>> taskCompleter = Completer<TaskInfo<T>>();

    /// 创建当前任务stream
    final StreamController<TaskInfo<T>> streamController = StreamController<TaskInfo<T>>();
    taskInfo.controller = streamController;

    /// 添加到任务队列
    _taskList.add(taskInfo);

    /// 当前任务的stream添加监听
    streamController.stream.listen((TaskInfo<T> completeTaskInfo) {
      if (completeTaskInfo.id == taskInfo.id) {
        taskCompleter.complete(completeTaskInfo);
        streamController.close();
      }
    });

    /// 触发任务
    _doTask();

    return taskCompleter.future;
  }

  void removeTask(String taskId) {
    TaskInfo<dynamic>? remove;
    for (int i = 0; i < _taskList.length; i++) {
      final TaskInfo<T> element = _taskList[i];
      if (element.taskId == taskId) {
        remove = element;
        break;
      }
    }
    if (remove != null) {
      _taskList.remove(remove);
    }
  }

  void cancelTask() {
    _taskList = [];
    _isCancelQueue = true;
    _mId = 0;
    _isTaskRunning = false;
    debugPrint('任务取消');
  }

  Future<void> _doTask() async {
    debugPrint('总任务数：${_taskList.length}, isTaskRunning: $_isTaskRunning');
    if (_isTaskRunning) {
      return;
    }
    if (_taskList.isEmpty) {
      return;
    }

    /// 取任务
    final TaskInfo<T> taskInfo = _taskList[0];
    _isTaskRunning = true;

    /// 模拟执行任务
    final result = await taskInfo.doSomething?.call();
    taskInfo.result = result;
    taskInfo.controller?.sink.add(taskInfo);

    if (_isCancelQueue) {
      debugPrint('任务取消成功');
      0.5.delay(() {
        cancelListener?.call();
      });
      return;
    }

    /// 出队列
    _taskList.removeAt(0);
    _isTaskRunning = false;

    /// 递归执行任务
    _doTask();
  }

  void disposed([String key = 'default']) {
    if (_instance.containsKey(key)) {
      _instance.remove(key);
    }
  }
}

class TaskInfo<T> {
  TaskInfo(this.id, this.taskId, this.doSomething, {this.controller});

  int id; // 任务唯一标识
  String? taskId;
  Future<T> Function()? doSomething;
  T? result;
  StreamController<TaskInfo>? controller;
}
